import ast

from django.core import serializers
from django.core.cache import cache

from django.http import JsonResponse, QueryDict, HttpResponse
from django.shortcuts import render, redirect
from django.core.validators import RegexValidator, EmailValidator, ValidationError
import json

from django.views.decorators.csrf import csrf_exempt
from django_redis import get_redis_connection

from app01 import models
from app01.forms.setupForm import PlatformModelForm, ExampleModelForm, ProductModelForm, FunDefineModelForm, DeviceModelForm, DeviceDataModelForm
from utils.encrypt import md5  # 引用自定义的加密md5
from django.core.validators import RegexValidator
from django.contrib.auth.mixins import LoginRequiredMixin  # 只有登录后才可使用的权限管理
# 定义forms表单验证的类
from django import forms
from django.forms import ModelChoiceField, HiddenInput
from django.forms.models import model_to_dict
from django.forms.widgets import Select
from django.core.serializers import serialize, deserialize


@csrf_exempt
def setup(request, mid=0, setup=''):
    if request.method == 'GET':
        # print('进入了setup=', setup, '  mid=', mid)
        # session_data = request.session.get('user_info')
        # session_email = session_data.get('email')
        # session_id = session_data.get('user_info')
        session_id = request.session.get('user_id')
        # 按照session查这个用户总共有几个平台
        admin_plat = models.AdminCustomer.objects.get(id=session_id)  # 其实查id一个就好email=session_email,
        # 反向查询（表要小写后边加_set）:get只查一条,filter查多条
        admin_plat = admin_plat.platform_set.all()  # .all() 和 first() 先给页面选择平台用

        # admin_plat_first = admin_plat.first()  # 暂时用不着
        # # 反向查询实例id表，默认都是第一条先(由js顶替,默认都先为空了)
        # plat_example = admin_plat_first.example_set.all()  # 暂时用不着
        # plat_example_first = plat_example.first()  # 暂时用不着

        form_plat = PlatformModelForm(initial={'toAdmin': session_id})  # 给页面录入平台资料,用户从session默认过来
        form_example = ExampleModelForm()
        form_product = ProductModelForm()
        form_fun = FunDefineModelForm()
        form_device = DeviceModelForm()
        context = {'admin_plat': admin_plat,  # 用户-平台
                   # 'plat_example': plat_example,  # 平台-实例，这个前端用不着了，用js顶替了
                   'form_plat': form_plat,
                   'form_example': form_example,
                   'form_product': form_product,
                   'form_fun': form_fun,
                   'form_device': form_device, }

        return render(request, 'setup/setup.html', context)  # 设置界面

    if request.method == 'POST':
        toId = []  # 本数据表保存后最后一笔记录的id和名称,后来不用了
        if setup == 'all':
            platPk = None
            examplePk = None
            productPk = None
            session_id = request.session.get('user_id')
            name = QueryDict(request.POST.get('editForm_plat')).get('name')
            platFirst = models.Platform.objects.filter(toAdmin_id=session_id, name=name).first()
            if platFirst:
                platPk = platFirst.pk
                form_plat = PlatformModelForm(QueryDict(request.POST.get('editForm_plat')), instance=platFirst)
            else:
                form_plat = PlatformModelForm(QueryDict(request.POST.get('editForm_plat')))

            iotInstanceId = QueryDict(request.POST.get('editForm_example')).get('iotInstanceId')
            exampleFirst = models.Example.objects.filter(toPlat_id=platPk, iotInstanceId=iotInstanceId).first()
            if exampleFirst:
                examplePk = exampleFirst.pk
                form_example = ExampleModelForm(QueryDict(request.POST.get('editForm_example')), instance=exampleFirst)
            else:
                form_example = ExampleModelForm(QueryDict(request.POST.get('editForm_example')))

            product_key = QueryDict(request.POST.get('editForm_product')).get('product_key')
            productFirst = models.Product.objects.filter(toExample_id=examplePk, product_key=product_key).first()
            if productFirst:
                productPk = productFirst.pk
                form_product = ProductModelForm(QueryDict(request.POST.get('editForm_product')), instance=productFirst)
            else:
                form_product = ProductModelForm(QueryDict(request.POST.get('editForm_product')))

            device_name = QueryDict(request.POST.get('editForm_device')).get('device_name')
            deviceFirst = models.Device.objects.filter(toProduct_id=productPk, device_name=device_name).first()
            if deviceFirst:
                devicePk = deviceFirst.pk
                form_device = DeviceModelForm(QueryDict(request.POST.get('editForm_device')), instance=deviceFirst)
            else:
                form_device = DeviceModelForm(QueryDict(request.POST.get('editForm_device')))

            # funcType = QueryDict(request.POST.get('editForm_fun')).get('funcType')
            # funFirst = models.FunDefine.objects.filter(toProductFuc_id=productPk, funcType=funcType).first()
            # if funFirst:
            #     funPk = funFirst.pk
            #     print('funPk:', funPk)
            #     form_fun = FunDefineModelForm(QueryDict(request.POST.get('editForm_fun')), instance=funFirst)
            # else:
            #     form_fun = FunDefineModelForm(QueryDict(request.POST.get('editForm_fun')))
            # funFirst = models.FunDefine.objects.filter(toProductFuc_id=productPk).first()
            my_list = request.session['my_list']
            if isinstance(my_list, str):
                # 使用ast.literal_eval()将字符串转换为列表(如果是简单的列表字符串直接用eval()则可)
                my_list = ast.literal_eval(my_list)
            # 校验通过的话:
            if form_plat.is_valid() and form_example.is_valid() and form_product.is_valid() and form_device.is_valid() and my_list:
                form1 = form_plat.save(commit=False)
                form1.save()

                form2 = form_example.save(commit=False)
                form2.toPlat = form1
                form2.save()

                form3 = form_product.save(commit=False)
                form3.toExample = form2
                form3.save()

                form4 = form_device.save(commit=False)
                form4.toProduct = form3
                form4.save()

                # form5 = form_fun.save(commit=False)
                # form5.toProductFuc = form3
                # form5.save()
                # 先删除原来已有的功能定义,再保存新的
                models.FunDefine.objects.filter(toProductFuc_id=productPk).delete()
                for item in my_list:
                    # 将字典转换为QueryDict
                    qdict = QueryDict('', mutable=True)
                    qdict.update(item["fields"])
                    mid = item.get('pk')
                    if mid:
                        funFirst = models.FunDefine.objects.filter(id=mid).first()
                        if funFirst:
                            funPk = funFirst.pk
                            form_fun = FunDefineModelForm(qdict, instance=funFirst)
                        else:
                            form_fun = FunDefineModelForm(qdict)
                    else:
                        form_fun = FunDefineModelForm(qdict)
                    if form_fun.is_valid():
                        form5 = form_fun.save(commit=False)
                        form5.toProductFuc = form3
                        form5.save()
                    else:
                        print('校验没通过：', item)
            else:
                edit1, edit2, edit3, edit4, edit5 = '', '', '', '', ''
                if not form_plat.is_valid():
                    edit1 = '有必填项没填，或平台名称必须包含：阿里，百度，腾讯，华为这些平台字样(现在只支持阿里)！'
                if not form_example.is_valid():
                    edit2 = '有必填项没填！'
                if not form_product.is_valid():
                    edit3 = '有必填项没填！'
                if not form_device.is_valid():
                    edit4 = '有必填项没填！'
                if not my_list:
                    edit5 = '有必填项没填！'
                return JsonResponse({'status': False, 'errors': [edit1, edit2, edit3, edit4, edit5]})
            return JsonResponse({'status': True})

        if setup == 'plat':
            if mid == 0:
                form_plat = PlatformModelForm(request.POST)
            else:
                obj_plat = models.Platform.objects.filter(id=mid).first()
                form_plat = PlatformModelForm(request.POST,
                                              instance=obj_plat)  # (request.POST)里有值就进行校验,instance起更新还是新增作用
            if not form_plat.is_valid():
                return JsonResponse({'status': '有必填项没填！', 'toId': toId})
            # 更新或新增，因为有加instance参数
            instance = form_plat.save()
            toId = [instance.pk, instance.name]  # 获取记录的ID
            return JsonResponse({'status': '平台保存成功', 'toId': toId})

        elif setup == 'example':
            if mid == 0:
                form_example = ExampleModelForm(request.POST)
            else:
                obj_example = models.Example.objects.filter(id=mid).first()
                form_example = ExampleModelForm(request.POST,
                                                instance=obj_example)  # (request.POST)里有值就进行校验,instance起更新还是新增作用
            if not form_example.is_valid():
                return JsonResponse({'status': '有必填项没填！', 'toId': toId})
            # 更新或新增，因为有加instance参数
            instance = form_example.save()
            toId = [instance.pk, instance.iotInstanceId]  # 获取记录的ID和名称
            return JsonResponse({'status': '实例保存成功', 'toId': toId})

        elif setup == 'product':
            if mid == 0:
                form_product = ProductModelForm(request.POST)
            else:
                obj_product = models.Product.objects.filter(id=mid).first()
                form_product = ProductModelForm(request.POST,
                                                instance=obj_product)  # (request.POST)里有值就进行校验,instance起更新还是新增作用
            if not form_product.is_valid():
                return JsonResponse({'status': '有必填项没填！', 'toId': toId})
            # 更新或新增，因为有加instance参数
            instance = form_product.save()
            toId = [instance.pk, instance.product_key]  # 获取记录的ID和名称
            return JsonResponse({'status': '产品保存成功', 'toId': toId})

        elif setup == 'device':
            if mid == 0:
                form_device = DeviceModelForm(request.POST)
            else:
                obj_device = models.Device.objects.filter(id=mid).first()
                form_device = DeviceModelForm(request.POST,
                                              instance=obj_device)  # (request.POST)里有值就进行校验,instance起更新还是新增作用
            if not form_device.is_valid():
                return JsonResponse({'status': '有必填项没填！', 'toId': toId})
            # 更新或新增，因为有加instance参数
            instance = form_device.save()
            toId = [instance.pk, instance.device_name]  # 获取记录的ID和名称
            return JsonResponse({'status': '设备保存成功', 'toId': toId})

        # elif setup == 'funDefine':  # 功能定义(被funAction顶替了)
        #     # print('到funDefine这里了', 'mid=', mid)
        #     if mid == 0:  # 新增
        #         form_fun = FunDefineModelForm(request.POST)
        #     else:  # 检查新增,还是修改
        #         obj_fun = models.FunDefine.objects.filter(id=mid).first()
        #         form_fun = FunDefineModelForm(request.POST,
        #                                       instance=obj_fun)  # (request.POST)里有值就进行校验,instance起更新还是新增作用
        #     if not form_fun.is_valid():
        #         return JsonResponse({'status': '有必填项没填！', 'toId': toId})
        #     # 更新或新增，因为有加instance参数
        #     instance = form_fun.save()
        #     toId = [instance.pk, instance.funcName]  # 获取记录的ID和名称
        #     return JsonResponse({'status': '功能定义保存成功', 'toId': toId})

        elif setup == 'funAction':  # 功能定义单独临时保存,新增,修改,删除时
            # print('mid:' + str(mid))
            editForm_fun = request.POST
            my_list = request.session['my_list']
            if isinstance(my_list, str):
                # 使用ast.literal_eval()将字符串转换为列表(如果是简单的列表字符串直接用eval()则可)
                my_list = ast.literal_eval(my_list)

            if mid == 0:  # 新增
                # 先校验
                funData = FunDefineModelForm(editForm_fun)
                if not funData.is_valid():
                    return JsonResponse({'status': False, 'message': '有必填项没填'})
                # 把新增的功能定义添加到临时数据库中
                maa = {"fields": editForm_fun.dict()}
                my_list.append(maa)
                request.session['my_list'] = my_list
            else:  # 修改或者删除
                if editForm_fun.get('type'):
                    if editForm_fun.get('type') == '1':  # 修改时
                        # 点击修改时，要取的这个id的数据返回去修改
                        my_list = my_list[mid - 1]
                    if editForm_fun.get('type') == '2':  # 删除时
                        # 点击删除时，把这个id的数据删除
                        my_list.pop(mid - 1)
                        request.session['my_list'] = my_list
                else:
                    # editForm_fun有数据，则是修改后的数据，需要更新保存起来
                    # 先校验
                    funData = FunDefineModelForm(editForm_fun)
                    if not funData.is_valid():
                        return JsonResponse({'status': False, 'message': '有必填项没填'})
                    # 把修改的功能定义更新到临时数据库中
                    maa = editForm_fun.dict()
                    my_list[mid-1]['fields'] = maa
                    request.session['my_list'] = my_list
            # print('要返回的记录: ', my_list)
            return JsonResponse({'status': True, 'form_fun': my_list})
        else:
            return JsonResponse({'status': '传参发生错误！'})


def setupDelete(request):  # 删除数据
    aid = request.GET.get('aid')  # 要删除的id
    setup = request.GET.get('setup')  # 要在哪张表里删除
    # print('要删除的: ', aid, setup)
    if setup == 'Plat':
        models.Platform.objects.filter(id=aid).delete()
    if setup == 'Example':
        models.Example.objects.filter(id=aid).delete()
    if setup == 'Product':
        models.Product.objects.filter(id=aid).delete()
    if setup == 'Device':
        models.Device.objects.filter(id=aid).delete()
    return JsonResponse({'status': '删除成功'})


def mySelectPlat(request):
    # session_id = request.session.get('user_info').get('id')
    session_id = request.session.get('user_id')
    # pid为检索输入框内容或者被选择项的id
    pid = request.GET.get('pid')
    # cs对应哪张表的值
    cs = request.GET.get('cs')
    # print('输入框pid内容或者被选择项的id:', pid, ' 对应哪张表cs值:', cs)

    if cs == '0':
        plat_obj = models.Platform.objects.filter(name=pid).first()  # 传来是name(平台)
        if plat_obj:
            plat_example = plat_obj.example_set.all()  # 这个平台关联着多少个实例
            plat_obj = model_to_dict(plat_obj)  # 因为这个不是queryset对象
            plat_example = serializers.serialize('json', plat_example)
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obj': plat_obj, 'plat_example': plat_example})

    elif cs == '1':
        plat_obj = models.Platform.objects.filter(id=pid).first()  # 传来是id(平台)
        if plat_obj:
            plat_example = plat_obj.example_set.all()  # 这个平台关联着多少个实例
            plat_obj = model_to_dict(plat_obj)  # 因为这个不是queryset对象
            plat_example = serializers.serialize('json', plat_example)
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obj': plat_obj, 'plat_example': plat_example})

    elif cs == '2':
        plat_obj = models.Example.objects.filter(iotInstanceId=pid).first()  # 传来是iotInstanceId(实例)
        if plat_obj:
            plat_example = plat_obj.product_set.all()  # 这个实例关联着多少个产品
            plat_obj = model_to_dict(plat_obj)  # 因为这个不是queryset对象
            plat_example = serializers.serialize('json', plat_example)
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obj': plat_obj, 'plat_example': plat_example})

    elif cs == '3':
        plat_obj = models.Example.objects.filter(id=pid).first()  # 传来是id(实例)
        if plat_obj:
            plat_example = plat_obj.product_set.all()  # 这个实例关联着多少个产品
            plat_obj = model_to_dict(plat_obj)  # 因为这个不是queryset对象
            plat_example = serializers.serialize('json', plat_example)
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obj': plat_obj, 'plat_example': plat_example})

    elif cs == '4':
        plat_obj = models.Product.objects.filter(product_key=pid).first()  # 传来是Product(产品)
        if plat_obj:
            plat_example = plat_obj.device_set.all()  # 这个产品关联着多少个设备
            plat_obj = model_to_dict(plat_obj)  # 因为这个不是queryset对象
            plat_example = serializers.serialize('json', plat_example)
            product_fun = plat_obj.fundefine_set.all()  # 这个产品关联着多少个功能定义

            request.session['my_list'] = serializers.serialize('json', product_fun)
        else:
            # 清空临时功能定义表
            request.session['my_list'] = []
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obj': plat_obj, 'plat_example': plat_example})

    elif cs == '5':  # 这里需要多传一个fun功能定义数据给前端
        plat_obj = models.Product.objects.filter(id=pid).first()  # 传来是id(产品)
        if plat_obj:
            plat_example = plat_obj.device_set.all()  # 这个产品关联着多少个设备
            plat_example = serializers.serialize('json', plat_example)
            product_fun = plat_obj.fundefine_set.all()  # 这个产品关联着多少个功能定义
            product_fun = serializers.serialize('json', product_fun)
            plat_obj = model_to_dict(plat_obj)  # 因为这个不是queryset对象

            request.session['my_list'] = product_fun
        else:
            # 清空临时功能定义表
            request.session['my_list'] = []
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse(
            {'status': True, 'plat_obj': plat_obj, 'plat_example': plat_example, 'product_fun': product_fun})

    elif cs == '6':
        plat_obj = models.Device.objects.filter(device_name=pid).first()  # 传来是Device(设备)
        if plat_obj:
            plat_example = plat_obj.devicedata_set.all()  # 这个设备关联着多少个数据
            plat_obj = model_to_dict(plat_obj)  # 因为这个不是queryset对象
            plat_example = serializers.serialize('json', plat_example)
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obj': plat_obj, 'plat_example': plat_example})

    elif cs == '7':
        plat_obj = models.Device.objects.filter(id=pid).first()  # 传来是id(设备)
        if plat_obj:
            plat_example = plat_obj.devicedata_set.all()  # 这个设备关联着多少个数据
            plat_obj = model_to_dict(plat_obj)  # 因为这个不是queryset对象
            plat_example = serializers.serialize('json', plat_example)
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obj': plat_obj, 'plat_example': plat_example})

    # 以下8开始是作为下拉框选择项的重新赋值(新增以后需要重新赋值)
    elif cs == '8':
        plat_obja = models.Platform.objects.filter(toAdmin_id=pid).all()  # 传来是id(平台),作为光标进入选择框时重载内容,依照上一级关联
        if plat_obja:
            plat_obja = serializers.serialize('json', plat_obja)  # 因为这个不是queryset对象
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obja': plat_obja})

    elif cs == '9':
        plat_obja = models.Example.objects.filter(toPlat_id=pid).all()  # 传来是id(实例),作为光标进入选择框时重载内容,依照上一级关联
        if plat_obja:
            plat_obja = serializers.serialize('json', plat_obja)  # 因为这个不是queryset对象
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obja': plat_obja})

    elif cs == '10':
        plat_obja = models.Product.objects.filter(toExample_id=pid).all()  # 传来是id(产品),作为光标进入选择框时重载内容,依照上一级关联
        if plat_obja:
            plat_obja = serializers.serialize('json', plat_obja)  # 因为这个不是queryset对象
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obja': plat_obja})

    elif cs == '11':
        plat_obja = models.Device.objects.filter(toProduct_id=pid).all()  # 传来是id(设备),作为光标进入选择框时重载内容,依照上一级关联
        if plat_obja:
            plat_obja = serializers.serialize('json', plat_obja)  # 因为这个不是queryset对象
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obja': plat_obja})

    elif cs == '12':  # 功能定义查询
        plat_obja = models.FunDefine.objects.filter(toProductFuc_id=pid).all()  # 传来是id(设备),作为光标进入选择框时重载内容,依照上一级关联
        if plat_obja:
            plat_obja = serializers.serialize('json', plat_obja)  # 因为这个不是queryset对象
        else:
            return JsonResponse({'status': False})  # 传参错误
        return JsonResponse({'status': True, 'plat_obja': plat_obja})

    elif cs == '13':  # 左侧动态树状结构
        data = []
        # 按照session查这个用户总共有几个平台
        if session_id is None:
            return redirect('/index/')  # 未登录，返回登录首页界面

        admin_plat = models.AdminCustomer.objects.get(id=session_id)  # 其实查id一个就好email=session_email,
        # 反向查询（表要小写后边加_set）:get只查一条,filter查多条
        admin_plat = admin_plat.platform_set.all()  # 反向查出有多少个平台
        if admin_plat:
            # admin_plat = serializers.serialize('json', admin_plat)  # 因为这个不是queryset对象
            for item in admin_plat:
                item_pk = '1-'+str(item.pk)
                dict = {
                    # "id": item.pk,
                    "id": item_pk,
                    "parent": '#',
                    "text": item.name,
                    "icon": "/static/images/title/people-fill.svg",
                    "href": "#",
                    "state": {
                        "opened": True,
                        "disabled": False,
                    }
                }
                data.append(dict)
                plat_example = item.example_set.all()  # 反向查出有多少个实例
                if plat_example:
                    for itemEx in plat_example:
                        itemEx_pk = '2-' + str(itemEx.pk)
                        dictEx = {
                            # "id": itemEx.pk,
                            "id": itemEx_pk,
                            "parent": item_pk,
                            "text": itemEx.iotInstanceId_alias,
                            "icon": "/static/images/title/person-fill.svg",
                            "href": "#",
                            "state": {
                                "opened": True,
                                "disabled": False,
                            }
                        }
                        data.append(dictEx)
                        example_product = itemEx.product_set.all()  # 反向查出有多少个产品
                        if example_product:
                            for itemPr in example_product:
                                itemPr_pk = '3-'+str(itemPr.pk)
                                dictDr = {
                                    # "id": itemPr.pk,
                                    "id": itemPr_pk,
                                    "parent": itemEx_pk,
                                    "text": itemPr.product_key_alias,
                                    "icon": "/static/images/title/person-fill-add.svg",
                                    "href": "#",
                                    "state": {
                                        "opened": True,
                                        "disabled": False,
                                    }
                                }
                                data.append(dictDr)
                                product_device = itemPr.device_set.all()  # 反向查出有多少个设备
                                if product_device:
                                    for itemDe in product_device:
                                        # itemDe_pk = '4-' + str(itemDe.pk)
                                        dictDe = {
                                            "id": itemDe.pk,
                                            # "id": itemDe_pk,
                                            "parent": itemPr_pk,
                                            "text": itemDe.device_name_alias,
                                            "li_attr": {"style": "color: #00AAB7;"},  # 设置节点颜色为绿色
                                            "icon": "/static/images/title/person-check.svg",
                                            "href": "/iot/connect/",
                                            "state": {
                                                "opened": True,
                                                "disabled": False,
                                            }
                                        }
                                        data.append(dictDe)
            return JsonResponse({'status': True, 'data': data})
        else:
            return JsonResponse({'status': False, 'data': '空'})  # 传参错误

    else:
        return JsonResponse({'status': False})  # 传参错误
